<?php

namespace app\base\command;
define('GLOBAL_START', 1);
use Workerman\Worker;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Cache;

class GatewayService extends Command
{
    protected $input;
    protected $output;

    protected function configure()
    {
        $this->setName('gateway:start')
            ->addArgument('action', 1, 'start|stop|restart|reload|status|connections')
            // 增加守护进程选项
            ->addOption('daemon', 'd', null, '以守护进程模式运行')
            ->setDescription('启动GatewayWorker服务');
    }

    protected function execute(Input $input, Output $output)
    {
        $this->input = $input;
        $this->output = $output;
        // 添加服务启动日志
        $this->output->writeln('<info>['.date('Y-m-d H:i:s').'] 正在启动GatewayWorker服务...</info>');

        try {
            // 初始化各服务
            $this->startRegister();
            $this->startBusinessWorker();
            $this->startGateway();

            // 在运行所有工作进程之前添加日志
            $this->output->writeln('<info>['.date('Y-m-d H:i:s').'] 即将运行所有工作进程...</info>');
            // 设置信号处理器
            pcntl_signal(SIGTERM, [$this, 'onSignal']);
            pcntl_signal(SIGINT, [$this, 'onSignal']);
            Worker::runAll();

            // 如果 Worker::runAll() 返回（正常情况下不会返回），则记录日志
            $this->output->writeln('<warning>['.date('Y-m-d H:i:s').'] Worker::runAll() 已返回，这通常表示事件循环已结束。</warning>');
        } catch (\Exception $e) {
            // 异常日志记录
            $this->output->writeln('<error>['.date('Y-m-d H:i:s').'] 服务启动失败: '.$e->getMessage().'</error>');
            throw $e;
        }
    }

    public function onSignal($signal)
    {
        // 处理信号，优雅地关闭服务
        $this->output->writeln('<info>['.date('Y-m-d H:i:s').'] 收到信号：'.$signal.', 准备关闭服务...</info>');
        Worker::stopAll();
    }

    private function startRegister()
    {
        $register = new Register('text://0.0.0.0:1238');
        $register->secretKey = 'your_secure_key_123'; // 必须添加

        // 注册中心日志
        $register->onWorkerStart = function($worker) {
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] Register worker {$worker->id} 启动成功</info>");
        };

        $register->onWorkerStop = function($worker) {
            $this->output->writeln("<comment>[".date('Y-m-d H:i:s')."] Register worker {$worker->id} 已停止</comment>");
        };

        // 添加 onError 回调来捕获可能的错误
        $register->onError = function($connection, $code, $msg) {
            $this->output->writeln("<error>[".date('Y-m-d H:i:s')."] Register worker 错误: $code - $msg</error>");
        };
    }

    private function startBusinessWorker()
    {
        $worker = new BusinessWorker();
        $worker->name = 'BusinessWorker';
        $worker->count = 4;
        $worker->registerAddress = '127.0.0.1:1238';
        $worker->secretKey = 'your_secure_key_123'; // 新增此行
        // 设置业务处理类
        $worker->eventHandler = \app\base\service\GatewayEvents::class;

        // 业务Worker日志
        $worker->onWorkerStart = function($worker) {
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] BusinessWorker {$worker->id} 启动成功</info>");
        };

        $worker->onWorkerStop = function($worker) {
            $this->output->writeln("<comment>[".date('Y-m-d H:i:s')."] BusinessWorker {$worker->id} 已停止</comment>");
        };

        // 错误日志
        $worker->onError = function($connection, $code, $msg) {
            $this->output->writeln("<error>[".date('Y-m-d H:i:s')."] 业务Worker异常: $code - $msg</error>");
        };

        // 添加 onConnect 和 onClose 回调来监控连接状态
        $worker->onConnect = function($connection) {
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] 业务Worker 连接建立</info>");
        };

        $worker->onClose = function($connection) {
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] 业务Worker 连接关闭</info>");
        };
    }

    private function startGateway()
    {
        $gateway = new Gateway("websocket://0.0.0.0:7879");
        // Windows环境强制单进程
        /* 网关进程数设置 (Windows系统强制设置为1进程) */
        $gateway->count = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? 1 : $this->getOptimalProcessCount();

        /* 网关基础配置 */
        $gateway->name = 'Gateway';
        $gateway->count = $this->getOptimalProcessCount();

        /* 网络通信配置 */
        $gateway->lanIp = '127.0.0.1';
        $gateway->startPort = 2300;
        $gateway->registerAddress = '127.0.0.1:1238';

        /* 安全密钥配置 */
        $gateway->secretKey = 'your_secure_key_123';

        /* 心跳检测配置
         * @param int $pingInterval 心跳间隔(秒)
         * @param int $pingNotResponseLimit 最大无响应次数
         * @param string $pingData 心跳数据包(JSON格式)
         */
        $gateway->pingInterval = 30;
        $gateway->pingNotResponseLimit = 10;
        $gateway->pingData = json_encode(['action' => 'ping']);

        /* 进程启动回调
         * 记录带时间戳的worker启动日志
         * @param Worker $worker worker实例对象
         */

        // 合并原有启动日志
        $existingCallback = $gateway->onWorkerStart;
        $gateway->onWorkerStart = function($worker) use ($existingCallback) {
            if ($existingCallback) $existingCallback($worker);
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] Gateway worker {$worker->id} 启动成功</info>");
        };

        $gateway->onWorkerStop = function($worker) {
            $this->output->writeln("<comment>[".date('Y-m-d H:i:s')."] Gateway worker {$worker->id} 已停止</comment>");
        };

        // 连接异常日志
        $gateway->onError = function($connection, $code, $msg) {
            $this->output->writeln("<error>[".date('Y-m-d H:i:s')."] 网关连接异常: $code - $msg</error>");
        };

        // 添加 onConnect 和 onClose 回调来监控连接状态
        $gateway->onConnect = function($connection) {
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] 网关连接建立</info>");
        };

        $gateway->onClose = function($connection) {
            $this->output->writeln("<info>[".date('Y-m-d H:i:s')."] 网关连接关闭</info>");
        };
    }

    private function getOptimalProcessCount()
    {
        // Windows系统强制单进程
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            return 1; // Windows不支持多进程
        }

        // Linux/Mac使用nproc检测
        $cpuCount = (int)shell_exec('nproc');
        return $cpuCount > 0 ? $cpuCount * 2 : 4;
    }
}
